/*
 * putcommand.cpp
 *
 *  Created on: Nov 16, 2009
 *      Author: kevin
 */

#include <iostream>
using std::endl;
using std::cout;

#include <string>
using std::string;

#include <sstream>
using std::ostringstream;
using std::istringstream;

#include "putcommand.h"

#include <Poco/StringTokenizer.h>
using Poco::StringTokenizer;

#include <Poco/Thread.h>
using Poco::Thread;

#include <Poco/DOM/DOMParser.h>
using Poco::XML::DOMParser;

#include <Poco/DOM/DOMWriter.h>
using Poco::XML::DOMWriter;

#include <Poco/DOM/Element.h>
using Poco::XML::Element;

#include <Poco/DOM/NodeList.h>
using Poco::XML::NodeList;

#include <Poco/Net/StreamSocket.h>
using Poco::Net::StreamSocket;

#include <Poco/Net/Socket.h>
using Poco::Net::Socket;

#include <Poco/FileStream.h>
using Poco::FileOutputStream;

#include <Poco/Net/SocketStream.h>
using Poco::Net::SocketStream;

#include <Poco/StreamCopier.h>
using Poco::StreamCopier;

namespace Commands {

	const string PutCommand::NAME = "Put";

	PutCommand::PutCommand( string const& fName, SocketAddress* s) :
		Command( s , true),
		fileName( fName ),
		putty(fName)
	{
	}

	PutCommand::~PutCommand() {
	}

	void PutCommand::execute(){
		Thread* downloader = new Thread("downloader");
		cout << "PutCommand :: Goint to start file transmission thread" << endl;
		downloader->start(putty);
		ostringstream os; os << putty.port();
		cout << "PutCommand :: Sending port " << os.str() << endl;
		setResult(os.str());
	}

	string PutCommand::name()
	{
		return string(PutCommand::NAME);
	}

	void PutCommand::undo()
	{
		throw NotImplemented();
	}

	string PutCommand::repr()
	{
		ostringstream out;
		DOMWriter w;
		w.writeNode(out, toXML());
		return out.str();
	}

	CommandCreator PutCommand::creator()
	{
		return PutCommand::makeCommand;
	}

	Document* PutCommand::toXML(Document* )
	{
		Document* doc = new Document();
		
		//What do we want to put
		Element* file = doc->createElement("file");
		file->setAttribute("name", fileName);
		doc->appendChild(file);

		return Command::toXML(doc);
	}

	Command* PutCommand::makeCommand(string r, void* s)
	{
		Socket* sock = (Socket*) s;
		DOMParser parser;
		Document* doc = parser.parseString(r);

		//Get the filename
		string fileName = ((Element*)(doc->getElementsByTagName("file")->item(0)))->getAttribute("name");
		cout << "PutCommand :: Creating Command :: " << fileName << endl;
		SocketAddress* address = new SocketAddress(sock->peerAddress());
		return new PutCommand( fileName, address );
	}
}
